package socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Server {
    // 服务器套接字
    private ServerSocket serverSocket;


    //
    private Map<String, PrintWriter> allOut =new HashMap<>();

    // 线程池
    private ExecutorService threadPool = Executors.newFixedThreadPool(50);
    public Server(){
        try {
            System.out.println("服务器启动中");
            serverSocket=new ServerSocket(8080);
            System.out.println("服务器启动成功");
        } catch (IOException e) {
            System.out.println("服务器关闭");
            e.printStackTrace();
        }
    }

    public void start(){

        //主线程用于接收用户的连接
        while (true){
            try {
                System.out.println("等待用户连接...");
                Socket socket=serverSocket.accept();
                System.out.println("一个用户连接成功");

                //启动线程处理用户连接
                Runnable handler=new ClientHandler(socket);
                threadPool.execute(handler);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {


        Server server=new Server();
        server.start();
    }

    public class ClientHandler implements Runnable{
        private Socket socket;
        private String nickname;
        private String host;
        public ClientHandler(Socket socket){
            this.socket=socket;
            host=socket.getInetAddress().getHostAddress();
        }
        public void run(){

            // 处理用户连接
            try {
                // 1.获取输入流
                InputStream is=socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(is, StandardCharsets.UTF_8);
                BufferedReader br=new BufferedReader(isr);
                nickname=br.readLine();

                // 2. 获取输出流
                OutputStream os=socket.getOutputStream();
                OutputStreamWriter osw=new OutputStreamWriter(os,StandardCharsets.UTF_8);
                BufferedWriter bw=new BufferedWriter(osw);
                PrintWriter pw=new PrintWriter(bw,true);
                //  处理并发
                synchronized (allOut) {
                    allOut.put(nickname, pw);
                }
                sendMessage(nickname+"上线了，当前在线人数："+allOut.size());
                // 3. 读取用户输入，发送给其他用户(循环）
                String messge;
                while ((messge=br.readLine())!=null){
                    if (messge.startsWith("@")){
                        sendMessageToOther(messge);
                    }else {
                        sendMessage(nickname+"群发说:"+messge);
                        //可以保存消息
                        saveMessage(nickname,null,messge);

                    }
                }

            }catch (Exception e){
                e.printStackTrace();
            }finally {
                sendMessage(nickname+"下线了,当前在线人数："+allOut.size());
                synchronized (allOut) {
                    allOut.remove(nickname);
                }
                try {
                    // 关闭流连接  进行四次挥手
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void sendMessage(String message){
            System.out.println(message);
            // 遍历所有输出流，发送消息
            synchronized (allOut) {
                for (PrintWriter pw : allOut.values()) {
                    pw.println(message);
                }
            }
        }
        private void sendMessageToOther(String message){
            //私聊消息
            //消息的拆分 解析
            String toName=message.substring(1,message.indexOf(":"));
            String content=message.substring(message.indexOf(":")+1);
            synchronized (allOut) {
                if (message.matches("@.+:.+")) {
                    if (allOut.containsKey(toName)) {
                        PrintWriter pw = allOut.get(toName);
                        pw.println(nickname + "悄悄对你说:" + content);
                        //可以保存消息
                        saveMessage(nickname,toName,content);
                    } else {
                        PrintWriter pw = allOut.get(nickname);
                        // 通知发送方
                        pw.println("用户" + toName + "不在线,或该用户不存在!");
                    }
                } else {
                    PrintWriter pw = allOut.get(nickname);
                    // 通知发送方
                    pw.println("消息格式不正确");
                }
            }
        }
        //
        //保存聊天信息
        private void saveMessage(String fromUser ,String toUser ,String message){
            /*
            将三个信息插入到表中
             */
            try (
                    Connection connection = DBUtil.getConnection();
            ){
                String sql = "INSERT INTO chatinfo(from_user,to_user,content) VALUES(?,?,?)";
                System.out.println(sql);
                PreparedStatement ps=connection.prepareStatement(sql);
                ps.setString(1,fromUser);
                ps.setString(2,toUser);
                ps.setString(3,message);

                int num=ps.executeUpdate();
                if (num>0){
                    System.out.println("聊天信息保存成功");
                }else {
                    System.out.println("聊天信息保存失败");
                }

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}
